﻿using CSharpCompiler;
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class AssetManager : Singleton<AssetManager>
{
    [CompilerGenerated]
    private static Func<Asset, bool> <>f__am$cache10;
    [CompilerGenerated]
    private static Func<Asset, bool> <>f__am$cache11;
    [CompilerGenerated]
    private static Func<Asset, bool> <>f__am$cache12;
    [CompilerGenerated]
    private static Func<Asset, bool> <>f__am$cache13;
    [CompilerGenerated]
    private static Func<string, bool> <>f__am$cache14;
    [CompilerGenerated]
    private static Func<string, string> <>f__am$cacheD;
    [CompilerGenerated]
    private static Func<string, string> <>f__am$cacheE;
    [CompilerGenerated]
    private static Func<Asset, bool> <>f__am$cacheF;
    public static string animationExtension = ".anim";
    public static string assetbundleExtension = ".assetbundle";
    private Dictionary<string, Asset> assetLookup = new Dictionary<string, Asset>(StringComparer.CurrentCultureIgnoreCase);
    public const string builtinFolderShortName = "__Builtin";
    private List<string> bundledAssetNames = new List<string>();
    private static Dictionary<object, object> caches = new Dictionary<object, object>();
    public const string databaseExtension = ".xls";
    public const string databaseFolderShortName = "Databases";
    private Dictionary<string, Asset> guidAssetLookup = new Dictionary<string, Asset>();
    public const string levelExtension = ".level";
    [SerializeField]
    private List<Asset> m_assets = new List<Asset>();
    [SerializeField]
    private UnityEngine.Object m_internalAssetRootFolder;
    private static GameObject m_prefabPool;
    public const string miscFolderShortName = "Misc";
    public const string moneyAssetName = "__Builtin/Prefabs/Items/Consumables/Money";
    public static string prefabExtension = ".prefab";
    public static string rawModelExtension = ".vox";
    public static string scriptExtension = ".cs";
    public const string templateFolderShortName = "Templates";
    public const string workspaceFolderShortName = "Workspace";

    private void Awake()
    {
        if (<>f__am$cacheD == null)
        {
            <>f__am$cacheD = x => x.Replace(@"\", "/");
        }
        string[] strArray = Directory.GetFiles(streamingAssetsPath, "*.*", SearchOption.AllDirectories).Select<string, string>(<>f__am$cacheD).ToArray<string>();
        if (<>f__am$cacheE == null)
        {
            <>f__am$cacheE = x => x.Replace(@"\", "/");
        }
        string[] source = Directory.GetFiles(streamingAssetsPath + "/__Builtin/Templates", "*.prefab", SearchOption.AllDirectories).Select<string, string>(<>f__am$cacheE).ToArray<string>();
        for (int i = 0; i < strArray.Length; i++)
        {
            string path = strArray[i];
            string extension = Path.GetExtension(path);
            if (((extension == rawModelExtension) || (extension == ".level")) || ((extension == assetbundleExtension) || (extension == animationExtension)))
            {
                Asset asset;
                asset = new Asset {
                    name = Path.ChangeExtension(path.Replace(streamingAssetsPath + "/", string.Empty), null),
                    name = this.TryGroupAssetName(asset.name),
                    dataFileName = path,
                    extension = extension
                };
                if (extension == rawModelExtension)
                {
                    string str3 = path;
                    string str4 = Path.ChangeExtension(str3, prefabExtension);
                    asset.modelFileName = str3;
                    asset.extension = prefabExtension;
                    if (File.Exists(str4))
                    {
                        asset.dataFileName = str4;
                    }
                    else
                    {
                        <Awake>c__AnonStorey65 storey = new <Awake>c__AnonStorey65 {
                            templateFolderName = streamingAssetsPath + "/__Builtin/Templates/" + asset.categoryWithoutAuthor
                        };
                        string str5 = source.FirstOrDefault<string>(new Func<string, bool>(storey.<>m__E7));
                        if (!File.Exists(str5))
                        {
                            continue;
                        }
                        asset.dataFileName = str5;
                    }
                }
                this.m_assets.Add(asset);
            }
        }
        this.RemoveAllAssetsInsideGroupedAsset();
        foreach (Asset asset2 in this.m_assets)
        {
            if (!this.assetLookup.ContainsKey(asset2.name))
            {
                this.assetLookup[asset2.name] = asset2;
            }
            else
            {
                object[] args = new object[] { asset2.name };
                Debug.LogErrorFormat("Duplicated asset '{0}' ", args);
            }
        }
        foreach (Asset asset3 in this.assetLookup.Values)
        {
            string guid = asset3.guid;
            if (!string.IsNullOrEmpty(guid))
            {
                if (!this.guidAssetLookup.ContainsKey(guid) && this.assetLookup.ContainsKey(asset3.name))
                {
                    this.guidAssetLookup[guid] = asset3;
                }
                else
                {
                    object[] objArray2 = new object[] { guid, asset3.name };
                    Debug.LogErrorFormat("Duplicated guid '{0}' '{1}'. ", objArray2);
                }
            }
        }
        LoadScripts();
        RegisterNetworkPrefabs();
    }

    private static Assembly CompileFiles(params string[] filePaths)
    {
        if (filePaths.Length == 0)
        {
            return null;
        }
        if (<>f__am$cache14 == null)
        {
            <>f__am$cache14 = x => File.Exists(x);
        }
        filePaths = filePaths.Where<string>(<>f__am$cache14).ToArray<string>();
        CompilerParameters options = new CompilerParameters {
            GenerateExecutable = false,
            GenerateInMemory = true
        };
        string[] textArray1 = new string[] { typeof(GameObject).Assembly.Location, typeof(Image).Assembly.Location, typeof(AssetManager).Assembly.Location, typeof(GameObjectExtension).Assembly.Location };
        options.ReferencedAssemblies.AddRange(textArray1);
        CompilerResults results = new CSharpCompiler.CodeCompiler().CompileAssemblyFromFileBatch(options, filePaths.ToArray<string>());
        IEnumerator enumerator = results.Errors.GetEnumerator();
        try
        {
            while (enumerator.MoveNext())
            {
                object current = enumerator.Current;
                Debug.LogError(current.ToString().Replace(@"\", "/").Replace(Application.dataPath + "/", string.Empty));
            }
        }
        finally
        {
            IDisposable disposable = enumerator as IDisposable;
            if (disposable == null)
            {
            }
            disposable.Dispose();
        }
        return results.CompiledAssembly;
    }

    [ContextMenu("RefreshInternalAssets")]
    public void EditorLoadInternalAssets()
    {
    }

    public static System.Type FindType(string typeName)
    {
        return FindType(null, typeName);
    }

    public static System.Type FindType(string author, string typeName)
    {
        System.Type type = System.Type.GetType(typeName);
        if (type == null)
        {
            type = System.Type.GetType(typeName + ", Assembly-CSharp");
        }
        if ((type == null) && (externalAssemblies != null))
        {
            Assembly assembly = null;
            if (!string.IsNullOrEmpty(author))
            {
                externalAssemblies.TryGetValue(author, out assembly);
                if (assembly != null)
                {
                    type = assembly.GetType(typeName);
                }
            }
            if (type == null)
            {
                externalAssemblies.TryGetValue("__Builtin", out assembly);
                if (assembly != null)
                {
                    type = assembly.GetType(typeName);
                }
            }
        }
        return type;
    }

    private static string FixFileName(string fileName)
    {
        fileName = fileName.Replace(@"\", "/");
        if (!fileName.StartsWithIgnoreCase((streamingAssetsPath + "/")))
        {
            fileName = streamingAssetsPath + "/" + fileName;
        }
        return fileName;
    }

    public static Asset[] GetAllAssets()
    {
        return Singleton<AssetManager>.Instance.m_assets.ToArray();
    }

    public static Asset[] GetAllItemAssets()
    {
        if (<>f__am$cache11 == null)
        {
            <>f__am$cache11 = x => IsItem(x.name);
        }
        return GetAllAssets().Where<Asset>(<>f__am$cache11).ToArray<Asset>();
    }

    public static Asset[] GetAllLevelAssets()
    {
        if (<>f__am$cacheF == null)
        {
            <>f__am$cacheF = x => IsLevel(x.name);
        }
        return GetAllAssets().Where<Asset>(<>f__am$cacheF).ToArray<Asset>();
    }

    public static Asset[] GetAllPrefabAssets()
    {
        if (<>f__am$cache10 == null)
        {
            <>f__am$cache10 = x => IsPrefab(x.name);
        }
        return GetAllAssets().Where<Asset>(<>f__am$cache10).ToArray<Asset>();
    }

    public static Asset[] GetAllSuitAssets()
    {
        if (<>f__am$cache13 == null)
        {
            <>f__am$cache13 = x => IsSuit(x.name);
        }
        return GetAllItemAssets().Where<Asset>(<>f__am$cache13).ToArray<Asset>();
    }

    public static Asset[] GetAllWeaponAssets()
    {
        if (<>f__am$cache12 == null)
        {
            <>f__am$cache12 = x => IsWeapon(x.name);
        }
        return GetAllItemAssets().Where<Asset>(<>f__am$cache12).ToArray<Asset>();
    }

    public static Asset GetAsset(string assetName)
    {
        Asset asset;
        if (string.IsNullOrEmpty(assetName))
        {
            return null;
        }
        Singleton<AssetManager>.Instance.assetLookup.TryGetValue(assetName, out asset);
        return asset;
    }

    public static Asset GetAssetByGuid(string guid)
    {
        Asset asset;
        if (string.IsNullOrEmpty(guid))
        {
            return null;
        }
        Singleton<AssetManager>.Instance.guidAssetLookup.TryGetValue(guid, out asset);
        return asset;
    }

    internal static T GetCache<T>(object key)
    {
        object obj2;
        caches.TryGetValue(key, out obj2);
        return (!(obj2 is T) ? default(T) : ((T) obj2));
    }

    public static Effect GetEffect(string assetName)
    {
        GameObject prefab = GetPrefab(assetName);
        return ((prefab == null) ? null : prefab.GetComponent<Effect>());
    }

    public static Item GetItem(string assetName)
    {
        GameObject prefab = GetPrefab(assetName);
        return ((prefab == null) ? null : prefab.GetComponent<Item>());
    }

    public static GameObject GetPrefab(string assetName)
    {
        Asset asset = GetAsset(assetName);
        return ((asset == null) ? null : asset.gameObject);
    }

    public static Asset GetPrefabAsset(string prefabName)
    {
        return GetAsset(prefabName);
    }

    public static Weapon GetWeapon(string assetName)
    {
        GameObject prefab = GetPrefab(assetName);
        return ((prefab == null) ? null : prefab.GetComponent<Weapon>());
    }

    public static bool HasAsset(string assetName)
    {
        return (GetAsset(assetName) != null);
    }

    public static bool HasModel(string fileName)
    {
        fileName = FixFileName(fileName);
        return File.Exists(fileName);
    }

    [RuntimeInitializeOnLoadMethod]
    private static void Init()
    {
        Singleton<AssetManager>.Instance.enabled = true;
    }

    public static bool IsConsumable(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Consumables/");
    }

    public static bool IsDecoration(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Decorations/");
    }

    public static bool IsEffect(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Effects/");
    }

    public static bool IsEnvironmentObject(string assetName)
    {
        return (((IsWall(assetName) || IsObstacle(assetName)) || IsFloor(assetName)) || IsDecoration(assetName));
    }

    public static bool IsFloor(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Floors/");
    }

    public static bool IsItem(string assetName)
    {
        return ((IsWeapon(assetName) || IsSuit(assetName)) || IsConsumable(assetName));
    }

    public static bool IsLevel(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Levels/");
    }

    public static bool IsMisc(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Misc/");
    }

    public static bool IsMonster(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Monsters/");
    }

    public static bool IsNPC(string assetName)
    {
        return assetName.ContainsIgnoreCase("/NPCs/");
    }

    public static bool IsObstacle(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Obstacles/");
    }

    public static bool IsPrefab(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Prefabs/");
    }

    public static bool IsSuit(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Suits/");
    }

    public static bool IsUnit(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Units/");
    }

    public static bool IsWall(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Walls/");
    }

    public static bool IsWeapon(string assetName)
    {
        return assetName.ContainsIgnoreCase("/Weapons/");
    }

    public static GameObject LoadModel(string fileName)
    {
        if (string.IsNullOrEmpty(fileName))
        {
            return null;
        }
        fileName = FixFileName(fileName);
        GameObject cache = GetCache<GameObject>(fileName);
        if (cache == null)
        {
            if (File.Exists(fileName))
            {
                cache = VoxelImporter.Load(fileName, new Vector3(0.5f, 0f, 0.5f), 0.06666667f);
                cache.name = fileName;
                cache.transform.parent = prefabPool.transform;
            }
            else
            {
                object[] args = new object[] { fileName };
                Debug.LogErrorFormat("Could not load model file '{0}', it doesn't exist.", args);
            }
            caches[fileName] = cache;
        }
        return cache;
    }

    private static void LoadScripts()
    {
        externalAssemblies = new Dictionary<string, Assembly>();
        foreach (string str in Directory.GetDirectories(streamingAssetsPath))
        {
            Assembly assembly = CompileFiles(Directory.GetFiles(str, "*.cs", SearchOption.AllDirectories));
            if (assembly != null)
            {
                string fileName = Path.GetFileName(str);
                externalAssemblies.Add(fileName, assembly);
            }
        }
    }

    public static string NavigatePath(string currentFolderPath, string navigator)
    {
        while (navigator.StartsWith("../"))
        {
            currentFolderPath = Path.GetDirectoryName(currentFolderPath);
            navigator = new string(navigator.Skip<char>(3).ToArray<char>());
        }
        return (currentFolderPath + "/" + navigator);
    }

    private static void RegisterNetworkPrefabs()
    {
        foreach (Asset asset in GetAllAssets())
        {
            if (NetworkUtility.IsNetworkDynamic(asset))
            {
                GameObject gameObject = asset.gameObject;
                if (asset.isInternalAsset && (gameObject.GetComponent<NetworkIdentity>() != null))
                {
                    ClientScene.RegisterPrefab(gameObject);
                }
                else
                {
                    gameObject.GetOrAddComponent<NetworkIdentity>();
                    gameObject.GetOrAddComponent<NetworkObject>();
                    gameObject.GetOrAddComponent<GameNetworkProximityChecker>();
                    NetworkHash128 newAssetId = NetworkHash128.Parse(ToMd5Hash(asset.name));
                    ClientScene.RegisterPrefab(gameObject, newAssetId);
                }
            }
        }
    }

    private void RemoveAllAssetsInsideGroupedAsset()
    {
        this.m_assets.RemoveAll(a => this.bundledAssetNames.Find(new Predicate<string>(new <RemoveAllAssetsInsideGroupedAsset>c__AnonStorey66 { a = a, <>f__this = this }.<>m__EF)) != null);
    }

    internal static void SetCache(object key, object value)
    {
        caches[key] = value;
    }

    private static string ToMd5Hash(string str)
    {
        using (MD5 md = MD5.Create())
        {
            StringBuilder builder = new StringBuilder();
            byte[] buffer = md.ComputeHash(Encoding.Unicode.GetBytes(str));
            for (int i = 0; i < buffer.Length; i++)
            {
                builder.Append(buffer[i].ToString("X2"));
            }
            return builder.ToString().ToLower();
        }
    }

    private string TryGroupAssetName(string assetName)
    {
        string fileName = Path.GetFileName(assetName);
        string directoryName = Path.GetDirectoryName(assetName);
        string str3 = Path.GetFileName(directoryName);
        if (fileName.ToLower() == str3.ToLower())
        {
            assetName = directoryName;
            this.bundledAssetNames.Add(assetName);
        }
        return assetName;
    }

    public static void Unload()
    {
        UnregisterNetworkObjects();
        UnloadScripts();
        caches.Clear();
        UnityEngine.Object.Destroy(Singleton<AssetManager>.Instance.gameObject);
        UnityEngine.Object.Destroy(prefabPool);
    }

    private static void UnloadScripts()
    {
    }

    private static void UnregisterNetworkObjects()
    {
        foreach (Asset asset in GetAllAssets())
        {
            if (NetworkUtility.IsNetworkDynamic(asset))
            {
                ClientScene.UnregisterPrefab(asset.gameObject);
            }
        }
    }

    public static Dictionary<string, Assembly> externalAssemblies
    {
        [CompilerGenerated]
        get
        {
            return <externalAssemblies>k__BackingField;
        }
        [CompilerGenerated]
        private set
        {
            <externalAssemblies>k__BackingField = value;
        }
    }

    public static UnityEngine.Object internalAssetRootFolder
    {
        get
        {
            return Singleton<AssetManager>.Instance.m_internalAssetRootFolder;
        }
    }

    internal static GameObject prefabPool
    {
        get
        {
            if (m_prefabPool == null)
            {
                m_prefabPool = new GameObject("__AssetManager_PrefabPool");
                m_prefabPool.SetActive(false);
                UnityEngine.Object.DontDestroyOnLoad(m_prefabPool);
            }
            return m_prefabPool;
        }
    }

    public static string streamingAssetsPath
    {
        get
        {
            return Application.streamingAssetsPath;
        }
    }

    public static string workshopAssetsPath
    {
        get
        {
            return (Application.dataPath + "/Workspace");
        }
    }

    [CompilerGenerated]
    private sealed class <Awake>c__AnonStorey65
    {
        internal string templateFolderName;

        internal bool <>m__E7(string x)
        {
            return this.templateFolderName.StartsWithIgnoreCase(Path.ChangeExtension(x, null));
        }
    }

    [CompilerGenerated]
    private sealed class <RemoveAllAssetsInsideGroupedAsset>c__AnonStorey66
    {
        internal AssetManager <>f__this;
        internal Asset a;

        internal bool <>m__EF(string b)
        {
            return (this.a.name.StartsWith(b + "/") && (this.a.name != b));
        }
    }
}

